package com.ssy.lingxi.enhance.serviceimpl.supplier;

import cn.hutool.core.collection.CollectionUtil;
import com.querydsl.core.BooleanBuilder;
import com.ssy.lingxi.common.exception.BusinessException;
import com.ssy.lingxi.common.model.dto.UserLoginCacheDTO;
import com.ssy.lingxi.common.response.PageData;
import com.ssy.lingxi.common.response.ResponseCode;
import com.ssy.lingxi.common.response.Wrapper;
import com.ssy.lingxi.enhance.api.model.dto.BatchExamDTO;
import com.ssy.lingxi.enhance.api.model.dto.UpdateStorageDTO;
import com.ssy.lingxi.enhance.constant.*;
import com.ssy.lingxi.enhance.entity.*;
import com.ssy.lingxi.enhance.handler.async.MessageAsyncService;
import com.ssy.lingxi.enhance.handler.async.ReportAsyncService;
import com.ssy.lingxi.enhance.handler.jpa.QueryDslUtil;
import com.ssy.lingxi.enhance.handler.utils.DoubleUtil;
import com.ssy.lingxi.enhance.model.bo.PNOReceiveDeliverDetailProductBO;
import com.ssy.lingxi.enhance.model.dto.AddStorageDTO;
import com.ssy.lingxi.enhance.model.dto.CommonIdDTO;
import com.ssy.lingxi.enhance.model.qo.ProduceNoticeOrderQO;
import com.ssy.lingxi.enhance.model.vo.ProduceNoticeOrderListVO;
import com.ssy.lingxi.enhance.repository.InnerWorkflowRecordRepository;
import com.ssy.lingxi.enhance.repository.OuterWorkflowRecordRepository;
import com.ssy.lingxi.enhance.repository.PNOReceiveDeliverDetailRepository;
import com.ssy.lingxi.enhance.repository.ProduceNoticeOrderRepository;
import com.ssy.lingxi.enhance.service.supplier.SupplierToBeAddStorageService;
import com.ssy.lingxi.message.api.constant.MessageTemplateCode;
import com.ssy.lingxi.product.api.enums.InvoicesTypeEnum;
import com.ssy.lingxi.product.api.feign.InvoicesControllerFeign;
import com.ssy.lingxi.product.api.model.request.warehouse.InvoicesAddFeignRequest;
import com.ssy.lingxi.product.api.model.request.warehouse.InvoicesDetailsListRequest;
import com.ssy.lingxi.product.api.model.request.warehouse.InvoicesDetailsRequest;
import com.ssy.lingxi.product.api.model.response.warehouse.InvoicesDetailsResponse;
import com.ssy.lingxi.report.api.enums.EnhanceSupplierOperateTypeEnum;
import com.ssy.lingxi.report.api.enums.OperateDataSourceEnum;
import com.ssy.lingxi.workflow.api.feign.ProcessFeign;
import com.ssy.lingxi.workflow.api.model.contant.ProcessTaskStatusEnum;
import com.ssy.lingxi.workflow.api.model.vo.request.TaskExecuteVO;
import com.ssy.lingxi.workflow.api.model.vo.response.SimpleTaskCompleteVO;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import javax.transaction.Transactional;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
import java.util.stream.Stream;

/**
 * 加工能力 - 指派生产通知单(供应商) - 待新增加工入库单 - 业务实现层
 * @author fhj
 * @date 2020/10/20
 * @version 2.0.0
 */
@Slf4j
@Service
public class SupplierToBeAddStorageServiceImpl implements SupplierToBeAddStorageService {

    @Resource
    private ProcessFeign processFeign;
    @Resource
    private QueryDslUtil queryDslUtil;
    @Resource
    private ProduceNoticeOrderRepository produceNoticeOrderRepository;
    @Resource
    private InvoicesControllerFeign invoicesControllerFeign;
    @Resource
    private InnerWorkflowRecordRepository innerWorkflowRecordRepository;
    @Resource
    private OuterWorkflowRecordRepository outerWorkflowRecordRepository;
    @Resource
    private PNOReceiveDeliverDetailRepository pnoReceiveDeliverDetailRepository;
    @Resource
    private ReportAsyncService reportAsyncService;
    @Resource
    private MessageAsyncService messageAsyncService;

    /**
     * 列表
     * */
    @Override
    public Wrapper<PageData<ProduceNoticeOrderListVO>> list(ProduceNoticeOrderQO qo, UserLoginCacheDTO user) {
        //查询表实体 - 生产通知单
        QProduceNoticeOrderDO pno = QProduceNoticeOrderDO.produceNoticeOrderDO;

        //查询条件构造 - 必要条件
        BooleanBuilder predicates = new BooleanBuilder();
        predicates.and(pno.supplierMemberId.eq(user.getMemberId()));
        predicates.and(pno.supplierRoleId.eq(user.getMemberRoleId()));
        predicates.and(pno.outerStatus.eq(PNOOuterStatusEnum.TO_BE_ADD_STORAGE.getCode()));

        return Wrapper.success(queryDslUtil.getSupplierPNOList(qo, pno, predicates));
    }

    /**
     * 提交
     * */
    @Override
    @Transactional
    public Wrapper<Void> submit(AddStorageDTO dto, UserLoginCacheDTO user) {
        //根据ID获取生产通知单详情
        ProduceNoticeOrderDO produceNoticeOrder = produceNoticeOrderRepository.findById(dto.getProduceNoticeOrderId()).orElse(null);
        if(produceNoticeOrder == null) {
            return Wrapper.fail(ResponseCode.ENHANCE_BY_ID_NOT_FOUND_PNO);
        }
        if(!produceNoticeOrder.getStatus().equals(PNOAllStatusEnum.TO_BE_SUPPLIER_ADD_STORAGE.getCode())) {
            return Wrapper.fail(ResponseCode.ENHANCE_ONLY_SUBMIT_INNER_STATUS_AS_TO_BE_SUPPLIER_ADD_STORAGE);
        }

        //收货总金额（结算金额，冗余起来方便结算服务查询）
        double receivePrice = 0.0;

        //根据生产通知单ID获取收货状态为待确认收货的生产通知单收发货明细商品
        PNOReceiveDeliverDetailDO pnoReceiveDeliverDetail = pnoReceiveDeliverDetailRepository.findByProduceNoticeOrderIdAndReceiveStatus(dto.getProduceNoticeOrderId(), ReceiveStatusEnum.TO_BE_CONFIRM_RECEIVE.getCode());
        List<PNOReceiveDeliverDetailProductBO> pnoReceiveDeliverDetailProductBOList = pnoReceiveDeliverDetail.getPnoReceiveDeliverDetailProductBOList();

        //根据生产通知单明细ID进行分组, 获取到每个生产通知单明细的入库数量总和。【key:生产通知单明细ID, value:入库数量总和】
        Map<Long, Double> map = dto.getStorageDetailsDTOList().stream().collect(Collectors.groupingBy(AddStorageDTO.StorageDetailsDTO::getProduceNoticeOrderDetailId, Collectors.summingDouble(AddStorageDTO.StorageDetailsDTO::getStorageCount)));

        //筛选不包含在发货单的商品, 如果有不包含的需要提示操作者重新操作, 需要选择发货单发货的商品
        List<Long> ids = map.keySet().stream().filter(id ->
                !pnoReceiveDeliverDetailProductBOList.stream().map(PNOReceiveDeliverDetailProductBO::getProduceNoticeOrderDetailId).collect(Collectors.toList()).contains(id))
                .collect(Collectors.toList());
        if(CollectionUtil.isNotEmpty(ids)) {
            List<String> productNames = dto.getStorageDetailsDTOList().stream().filter(a -> ids.contains(a.getProduceNoticeOrderDetailId()))
                    .map(AddStorageDTO.StorageDetailsDTO::getProductName).collect(Collectors.toList());
            return Wrapper.fail("不存在的发货单商品【" + productNames.toString() + "】, 请重新选择。");
        }

        //更新收发货明细：入库数量、差异数量
        for(PNOReceiveDeliverDetailProductBO bo:pnoReceiveDeliverDetailProductBOList) {
            bo.setStorageNum(map.get(bo.getProduceNoticeOrderDetailId()));
            bo.setDifferenceNum(DoubleUtil.sub(bo.getDeliverNum(), bo.getStorageNum()));

            //计算结算金额 = 入库数量 * 加工单价
            receivePrice = DoubleUtil.add(receivePrice, DoubleUtil.mul(bo.getProcessPrice(), bo.getStorageNum()));
        }

        //获取生产通知单的配送方式（是否为物流）
        boolean logistics = produceNoticeOrder.getDeliveryType().equals(DeliveryTypeEnum.LOGISTICS.getCode());

        //调用仓库服务 -> 添加单据内部接口
        InvoicesAddFeignRequest request = new InvoicesAddFeignRequest();
        request.setInvoicesTypeCode(InvoicesTypeEnum.PROCESSING_STOCK_IN.getCode());
        request.setInvoicesTypeId(InvoicesTypeEnum.PROCESSING_STOCK_IN.getId());
        request.setInvoicesType(InvoicesTypeEnum.PROCESSING_STOCK_IN.getName());
        request.setInvoicesAbstract(dto.getStorageSummary());
        request.setInventoryId(dto.getWarehouseId());
        request.setInventoryRole(dto.getWarehouseRole());
        request.setTransactionTime(dto.getStorageTime());
        request.setOrderNo(produceNoticeOrder.getNoticeNo());
        request.setState(1);
        request.setRelevanceInvoicesNo(produceNoticeOrder.getNoticeNo());
        request.setRelevanceInvoicesId(produceNoticeOrder.getId());
        request.setRelevanceInvoices(4);
        request.setDeliveryAddresId(logistics ? produceNoticeOrder.getReceiverAddressId() : produceNoticeOrder.getDeliveryAddressId());
        request.setReceiverName(logistics ? produceNoticeOrder.getReceiveUserName() : produceNoticeOrder.getDeliveryUserName());
        request.setFullAddress(logistics ? produceNoticeOrder.getReceiveAddress() : produceNoticeOrder.getDeliveryAddress());
        request.setPhone(logistics ? produceNoticeOrder.getReceiveUserTel() : produceNoticeOrder.getDeliveryUserTel());
        request.setDeliveryType(produceNoticeOrder.getDeliveryType());
        request.setCreateRoleId(user.getMemberRoleId());
        request.setCreateMemberId(user.getMemberId());
        request.setCreateMemberName(user.getCompany());
        request.setSupplyMembersName(user.getCompany());
        request.setSupplyMembersId(user.getMemberId());
        request.setSupplyMembersRoleId(user.getMemberRoleId());
        request.setSource(dto.getSource());
        request.setInvoicesDetailsRequests(dto.getStorageDetailsDTOList().stream().map(a -> {
            InvoicesDetailsRequest invoicesDetailsRequest = new InvoicesDetailsRequest();
            BeanUtils.copyProperties(a, invoicesDetailsRequest);
//            invoicesDetailsRequest.setGoodsName(a.getItemName());
//            invoicesDetailsRequest.setProductCount(a.getProcessNum());
            return invoicesDetailsRequest;
        }).collect(Collectors.toList()));
        Wrapper<InvoicesDetailsResponse> invoicesDetailsResponseWrapper = invoicesControllerFeign.invoicesAddFeign(request);
        if(ResponseCode.SUCCESS.getCode() == invoicesDetailsResponseWrapper.getCode()) {
            //更新生产通知单收发货明细：入库单号、入库单ID、入库时间、收货数量、结算金额
            pnoReceiveDeliverDetail.setStorageNo(invoicesDetailsResponseWrapper.getData().getInvoicesNo());
            pnoReceiveDeliverDetail.setStorageId(invoicesDetailsResponseWrapper.getData().getId());
            pnoReceiveDeliverDetail.setStorageTime(System.currentTimeMillis());
            pnoReceiveDeliverDetail.setReceiveNum(pnoReceiveDeliverDetailProductBOList.stream().mapToDouble(PNOReceiveDeliverDetailProductBO::getStorageNum).sum());
            pnoReceiveDeliverDetail.setReceivePrice(receivePrice);
            pnoReceiveDeliverDetailRepository.saveAndFlush(pnoReceiveDeliverDetail);

            //更新生产通知单：入库单ID、入库单号、状态、供应商内部状态
            produceNoticeOrder.setStorageId(invoicesDetailsResponseWrapper.getData().getId());
            produceNoticeOrder.setStorageNo(invoicesDetailsResponseWrapper.getData().getInvoicesNo());
            produceNoticeOrder.setStatus(PNOAllStatusEnum.TO_BE_SUPPLIER_EXAM_STORAGE.getCode());
            produceNoticeOrder.setSupplierInnerStatus(PNOSupplierInnerStatusEnum.TO_BE_EXAM_STORAGE.getCode());
            produceNoticeOrderRepository.saveAndFlush(produceNoticeOrder);
        }else {
            log.error("调用仓库服务异常:" + invoicesDetailsResponseWrapper.getMessage());
            throw new BusinessException(ResponseCode.SERVICE_WAREHOUSE_ERROR);
        }

        return Wrapper.success();
    }

    /**
     * 审核
     * */
    @Override
    @Transactional
    public Wrapper<Void> exam(CommonIdDTO dto, UserLoginCacheDTO user) {
        //根据ID获取生产通知单详情
        ProduceNoticeOrderDO produceNoticeOrder = produceNoticeOrderRepository.findById(dto.getId()).orElse(null);
        if(produceNoticeOrder == null) {
            return Wrapper.fail(ResponseCode.ENHANCE_BY_ID_NOT_FOUND_PNO);
        }
        if(!produceNoticeOrder.getStatus().equals(PNOAllStatusEnum.TO_BE_SUPPLIER_EXAM_STORAGE.getCode())) {
            return Wrapper.fail(ResponseCode.ENHANCE_ONLY_EXAM_INNER_STATUS_AS_TO_BE_SUPPLIER_EXAM_STORAGE);
        }

        //根据生产通知单ID获取收货状态为待确认收货的生产通知单收发货明细
        PNOReceiveDeliverDetailDO pnoReceiveDeliverDetailDO = pnoReceiveDeliverDetailRepository.findByProduceNoticeOrderIdAndReceiveStatus(dto.getId(), ReceiveStatusEnum.TO_BE_CONFIRM_RECEIVE.getCode());
        if(pnoReceiveDeliverDetailDO == null) {
            return Wrapper.fail(ResponseCode.ENHANCE_BY_ID_NOT_FOUND_PNO_RECEIVE_DELIVER_DETAIL);
        }

        //调用仓库服务 -> 审核单据内部接口
        InvoicesDetailsListRequest invoicesDetailsListRequest = new InvoicesDetailsListRequest();
        invoicesDetailsListRequest.setInvoicesId(pnoReceiveDeliverDetailDO.getStorageId());
        invoicesDetailsListRequest.setMemberId(user.getMemberId());
        invoicesDetailsListRequest.setMemberRoleId(user.getMemberRoleId());
        Wrapper<InvoicesDetailsResponse> invoicesDetailsResponseWrapper = invoicesControllerFeign.invoicesReview(invoicesDetailsListRequest);
        if(ResponseCode.SUCCESS.getCode() == invoicesDetailsResponseWrapper.getCode()) {
            //调用工作流服务 -> 执行外部流程
            TaskExecuteVO taskExecuteVO = new TaskExecuteVO();
            taskExecuteVO.setMemberId(produceNoticeOrder.getSupplierMemberId());
            taskExecuteVO.setRoleId(produceNoticeOrder.getSupplierRoleId());
            taskExecuteVO.setDataId(produceNoticeOrder.getId());
            taskExecuteVO.setTaskId(produceNoticeOrder.getOuterTaskId());
            taskExecuteVO.setAgree(ProcessTaskStatusEnum.GOTO_NEXT_STEP.getCode());
            taskExecuteVO.setProcessKey(produceNoticeOrder.getOuterProcessKey());
            Wrapper<SimpleTaskCompleteVO> outerWrapper = processFeign.completeSimpleTask(taskExecuteVO);
            if(ResponseCode.SUCCESS.getCode() == outerWrapper.getCode()) {
                //记录外部工作流记录
                OuterWorkflowRecordDO outerWorkflowRecordDO = new OuterWorkflowRecordDO();
                outerWorkflowRecordDO.setProduceNoticeOrderId(produceNoticeOrder.getId());
                outerWorkflowRecordDO.setUserId(user.getUserId());
                outerWorkflowRecordDO.setMemberId(user.getMemberId());
                outerWorkflowRecordDO.setRoleId(user.getMemberRoleId());
                outerWorkflowRecordDO.setStep(produceNoticeOrder.getOuterStatus());
                outerWorkflowRecordDO.setRoleName(user.getMemberRoleName());
                outerWorkflowRecordDO.setStatus("待收货生产通知单");
                outerWorkflowRecordDO.setOperate("新增加工入库单");
                outerWorkflowRecordDO.setOperateTime(System.currentTimeMillis());
                outerWorkflowRecordDO.setOpinion("入库单号：" + produceNoticeOrder.getStorageNo());
                outerWorkflowRecordRepository.saveAndFlush(outerWorkflowRecordDO);

                //记录供应商内部工作流记录
                InnerWorkflowRecordDO innerWorkflowRecord = new InnerWorkflowRecordDO();
                innerWorkflowRecord.setProduceNoticeOrderId(produceNoticeOrder.getId());
                innerWorkflowRecord.setUserId(user.getUserId());
                innerWorkflowRecord.setMemberId(user.getMemberId());
                innerWorkflowRecord.setRoleId(user.getMemberRoleId());
                innerWorkflowRecord.setType(RoleTypeEnum.SUPPLIER.getCode());
                innerWorkflowRecord.setStep(produceNoticeOrder.getStatus());
                innerWorkflowRecord.setOperator(user.getUserName());
                innerWorkflowRecord.setDepartment(user.getUserOrgName());
                innerWorkflowRecord.setJobTitle(user.getUserJobTitle());
                innerWorkflowRecord.setStatus("已审核加工入库单");
                innerWorkflowRecord.setOperate("新增加工入库单");
                innerWorkflowRecord.setOperateTime(System.currentTimeMillis());
                innerWorkflowRecord.setOpinion("入库单号：" + produceNoticeOrder.getStorageNo());
                innerWorkflowRecordRepository.saveAndFlush(innerWorkflowRecord);

                //更新外部状态、外部任务ID、状态、供应商内部状态
                produceNoticeOrder.setOuterStatus(outerWrapper.getData().getStatus());
                produceNoticeOrder.setOuterTaskId(outerWrapper.getData().getTaskId());
                produceNoticeOrder.setStatus(PNOAllStatusEnum.TO_BE_SUPPLIER_CONFIRM_RECEIVE.getCode());
                produceNoticeOrder.setSupplierInnerStatus(PNOSupplierInnerStatusEnum.TO_BE_CONFIRM_RECEIVE.getCode());
                produceNoticeOrderRepository.saveAndFlush(produceNoticeOrder);
            }else {
                log.error("调用工作流服务失败, 导致前面去调用了仓库服务的审核单据接口更新了发货单的审核状态, 需要将发货单回滚回待审核状态且相关业务");
                log.error("工作流服务异常:" + outerWrapper.getMessage());
                throw new BusinessException(ResponseCode.ENHANCE_WORKFLOW_ERROR);
            }
        }else {
            log.error("调用仓库服务异常:" + invoicesDetailsResponseWrapper.getMessage());
            throw new BusinessException(ResponseCode.SERVICE_WAREHOUSE_ERROR);
        }

        //调用报表服务、消息服务 -> 新增操作通知、发送系统消息（如果调用过程出现异常, 无需回滚, 直接catch打印日志正常返回。）
        reportAsyncService.addOperateNotice(
                user.getMemberId(), user.getMemberRoleId(), OperateDataSourceEnum.ENHANCE_SUPPLIER.getCode(),
                EnhanceSupplierOperateTypeEnum.TO_BE_RECEIVE.getCode(),  1L,
                EnhanceSupplierOperateTypeEnum.TO_BE_ADD_STORAGE.getCode(), 1L
        );
        messageAsyncService.sendSystemMessage(produceNoticeOrder.getSupplierMemberId(), produceNoticeOrder.getSupplierRoleId(),
                MessageTemplateCode.production_order_receive, Stream.of(produceNoticeOrder.getNoticeNo(), produceNoticeOrder.getSummary()).collect(Collectors.toList())
        );

        return Wrapper.success();
    }

    /**
     * 内部接口：修改入库单
     * */
    @Override
    @Transactional
    public Wrapper<Void> updateStorage(UpdateStorageDTO dto) {
        //根据ID获取生产通知单详情
        ProduceNoticeOrderDO produceNoticeOrder = produceNoticeOrderRepository.findById(dto.getProduceNoticeOrderId()).orElse(null);
        if(produceNoticeOrder == null) {
            return Wrapper.fail(ResponseCode.ENHANCE_BY_ID_NOT_FOUND_PNO);
        }

        //根据生产通知单ID和入库单ID获取生产通知单收发货明细
        PNOReceiveDeliverDetailDO pnoReceiveDeliverDetail = pnoReceiveDeliverDetailRepository.findByProduceNoticeOrderIdAndStorageId(dto.getProduceNoticeOrderId(), dto.getStorageId());
        if(pnoReceiveDeliverDetail == null) {
            return Wrapper.fail(ResponseCode.ENHANCE_BY_ID_NOT_FOUND_PNO_RECEIVE_DELIVER_DETAIL);
        }
        if(pnoReceiveDeliverDetail.getReceiveStatus().equals(ReceiveStatusEnum.ALREADY_CONFIRM_RECEIVE.getCode())) {
            return Wrapper.fail("供应商确认收货后就不能修改入库单");
        }

        //根据生产通知单明细ID进行分组, 获取到每个生产通知单明细的入库数量总和。【key:生产通知单明细ID, value:入库数量总和】
        Map<Long, Double> map = dto.getStorageDetailsDTOList().stream().collect(Collectors.groupingBy(UpdateStorageDTO.StorageDetailsDTO::getProduceNoticeOrderDetailId, Collectors.summingDouble(UpdateStorageDTO.StorageDetailsDTO::getStorageCount)));

        //筛选不包含在发货单的商品, 如果有不包含的需要提示操作者重新操作, 需要选择发货单发货的商品
        List<Long> ids = map.keySet().stream().filter(id ->
                !pnoReceiveDeliverDetail.getPnoReceiveDeliverDetailProductBOList().stream().map(PNOReceiveDeliverDetailProductBO::getProduceNoticeOrderDetailId).collect(Collectors.toList()).contains(id))
                .collect(Collectors.toList());
        if(CollectionUtil.isNotEmpty(ids)) {
            List<String> productNames = dto.getStorageDetailsDTOList().stream().filter(a -> ids.contains(a.getProduceNoticeOrderDetailId()))
                    .map(UpdateStorageDTO.StorageDetailsDTO::getProductName).collect(Collectors.toList());
            return Wrapper.fail("不存在的发货单商品【" + productNames.toString() + "】, 请重新选择。");
        }

        //更新收发货明细：入库数量、差异数量
        for(PNOReceiveDeliverDetailProductBO bo:pnoReceiveDeliverDetail.getPnoReceiveDeliverDetailProductBOList()) {
            bo.setStorageNum(map.get(bo.getProduceNoticeOrderDetailId()));
            bo.setDifferenceNum(DoubleUtil.sub(bo.getDeliverNum(), bo.getStorageNum()));
        }
        pnoReceiveDeliverDetailRepository.saveAndFlush(pnoReceiveDeliverDetail);

        return Wrapper.success();
    }

    /**
     * 内部接口：批量审核入库单
     * */
    @Override
    @Transactional
    public Wrapper<Void> batchExamStorage(BatchExamDTO dto) {
        //根据ID集合获取生产通知单集合
        List<ProduceNoticeOrderDO> produceNoticeOrderList = produceNoticeOrderRepository.findAllById(dto.getIdList());

        //校验
        if(CollectionUtil.isEmpty(produceNoticeOrderList)) {
            return Wrapper.fail(ResponseCode.ENHANCE_BY_ID_NOT_FOUND_PNO);
        }
        if(produceNoticeOrderList.stream().anyMatch(a -> !a.getStatus().equals(PNOAllStatusEnum.TO_BE_SUPPLIER_EXAM_STORAGE.getCode()))) {
            return Wrapper.fail(ResponseCode.ENHANCE_ONLY_EXAM_INNER_STATUS_AS_TO_BE_SUPPLIER_EXAM_STORAGE);
        }
        if(dto.getUser() == null) {
            return Wrapper.fail("当前登录会员信息不能为空");
        }

        //循环调用工作流服务, 调用成功时更新生产通知单, 调用失败直接返回, 不需要抛出异常, 因为前面调用成功的不需要回滚。
        for(ProduceNoticeOrderDO p:produceNoticeOrderList) {
            //根据生产通知单ID获取收货状态为待确认收货的生产通知单收发货明细
            PNOReceiveDeliverDetailDO pnoReceiveDeliverDetailDO = pnoReceiveDeliverDetailRepository.findByProduceNoticeOrderIdAndReceiveStatus(p.getId(), ReceiveStatusEnum.TO_BE_CONFIRM_RECEIVE.getCode());
            if(pnoReceiveDeliverDetailDO == null) {
                return Wrapper.fail(ResponseCode.ENHANCE_BY_ID_NOT_FOUND_PNO_RECEIVE_DELIVER_DETAIL);
            }

            //调用工作流服务 -> 执行外部流程
            TaskExecuteVO taskExecuteVO = new TaskExecuteVO();
            taskExecuteVO.setMemberId(p.getSupplierMemberId());
            taskExecuteVO.setRoleId(p.getSupplierRoleId());
            taskExecuteVO.setDataId(p.getId());
            taskExecuteVO.setTaskId(p.getOuterTaskId());
            taskExecuteVO.setAgree(ProcessTaskStatusEnum.GOTO_NEXT_STEP.getCode());
            taskExecuteVO.setProcessKey(p.getOuterProcessKey());
            Wrapper<SimpleTaskCompleteVO> outerWrapper = processFeign.completeSimpleTask(taskExecuteVO);
            if(ResponseCode.SUCCESS.getCode() == outerWrapper.getCode()) {
                //记录外部工作流记录
                OuterWorkflowRecordDO outerWorkflowRecordDO = new OuterWorkflowRecordDO();
                outerWorkflowRecordDO.setProduceNoticeOrderId(p.getId());
                outerWorkflowRecordDO.setUserId(dto.getUser().getUserId());
                outerWorkflowRecordDO.setMemberId(dto.getUser().getMemberId());
                outerWorkflowRecordDO.setRoleId(dto.getUser().getMemberRoleId());
                outerWorkflowRecordDO.setStep(p.getOuterStatus());
                outerWorkflowRecordDO.setRoleName(dto.getUser().getMemberRoleName());
                outerWorkflowRecordDO.setStatus("待收货生产通知单");
                outerWorkflowRecordDO.setOperate("新增加工入库单");
                outerWorkflowRecordDO.setOperateTime(System.currentTimeMillis());
                outerWorkflowRecordDO.setOpinion("入库单号：" + p.getStorageNo());
                outerWorkflowRecordRepository.saveAndFlush(outerWorkflowRecordDO);

                //记录供应商内部工作流记录
                InnerWorkflowRecordDO innerWorkflowRecord = new InnerWorkflowRecordDO();
                innerWorkflowRecord.setProduceNoticeOrderId(p.getId());
                innerWorkflowRecord.setUserId(dto.getUser().getUserId());
                innerWorkflowRecord.setMemberId(dto.getUser().getMemberId());
                innerWorkflowRecord.setRoleId(dto.getUser().getMemberRoleId());
                innerWorkflowRecord.setType(RoleTypeEnum.SUPPLIER.getCode());
                innerWorkflowRecord.setStep(p.getStatus());
                innerWorkflowRecord.setOperator(dto.getUser().getUserName());
                innerWorkflowRecord.setDepartment(dto.getUser().getUserOrgName());
                innerWorkflowRecord.setJobTitle(dto.getUser().getUserJobTitle());
                innerWorkflowRecord.setStatus("已审核加工入库单");
                innerWorkflowRecord.setOperate("新增加工入库单");
                innerWorkflowRecord.setOperateTime(System.currentTimeMillis());
                innerWorkflowRecord.setOpinion("入库单号：" + p.getStorageNo());
                innerWorkflowRecordRepository.saveAndFlush(innerWorkflowRecord);

                //更新外部状态、外部任务ID、状态
                p.setOuterStatus(outerWrapper.getData().getStatus());
                p.setOuterTaskId(outerWrapper.getData().getTaskId());
                p.setStatus(PNOAllStatusEnum.TO_BE_SUPPLIER_CONFIRM_RECEIVE.getCode());
                produceNoticeOrderRepository.saveAndFlush(p);
            }else {
                log.error("工作流服务异常:" + outerWrapper.getMessage());
                throw new BusinessException(ResponseCode.ENHANCE_WORKFLOW_ERROR);
            }

            //调用报表服务、消息服务 -> 新增操作通知、发送系统消息（如果调用过程出现异常, 无需回滚, 直接catch打印日志正常返回。）
            reportAsyncService.addOperateNotice(
                    dto.getUser().getMemberId(), dto.getUser().getMemberRoleId(), OperateDataSourceEnum.ENHANCE_SUPPLIER.getCode(),
                    EnhanceSupplierOperateTypeEnum.TO_BE_RECEIVE.getCode(),  1L,
                    EnhanceSupplierOperateTypeEnum.TO_BE_ADD_STORAGE.getCode(), 1L
            );
            messageAsyncService.sendSystemMessage(p.getSupplierMemberId(), p.getSupplierRoleId(),
                    MessageTemplateCode.production_order_receive, Stream.of(p.getNoticeNo(), p.getSummary()).collect(Collectors.toList())
            );
        }

        return Wrapper.success();
    }
}
